package edu.uwm.RobberKnight.View;

import java.awt.Color;
import java.awt.Graphics;
import java.util.LinkedList;

/*
 * A fire work show that generates and launches many random fire works.
 */
public class FireworkShow {
	
	//A note about the synchronized block
	//It appears the updateState methods and draw methods are called on different threads. I was getting
	//a ConcurrentModificationException and it appears this was due to the fact that _fireworks is being iterated
	//through in draw while _fireworks is being modified (by calling add() or remove()) in updateState()
	//By using the synchronized block we are saying that the code cannot be executed unless the collection is not already
	//being modified/iterated through.
	
	private LinkedList<Firework> _fireworks;
	private int _screenWidth;
	private int _screenHeight;
	private long _timeUntilNextFirework;
	private boolean _started;
	
	public FireworkShow() {
		_fireworks = new LinkedList<Firework>();
	}
	
	/*
	 * Update the firework show based on the time elapsed since the last update.
	 */
	public void updateState(long time, int screenWidth, int screenHeight) {
		_screenWidth = screenWidth;
		_screenHeight = screenHeight;
		
		if(_started) {
			_timeUntilNextFirework -= time;
			if(_timeUntilNextFirework <= 0) {
				synchronized(_fireworks) {
					_fireworks.add(generateRandomFirework());
				}
				//Next firework is at a random time between 0 and 1 seconds.
				_timeUntilNextFirework = (long) (Math.random() * 500);
			}
		}
		synchronized(_fireworks) {
			for(int i = _fireworks.size() - 1; i >= 0; i--) {
				Firework firework = _fireworks.get(i);
				firework.updateState(time);
				if(firework.isFinished()) {
					_fireworks.remove(i);
				}
			}
		}
	}
	
	/*
	 * Start the firework show.
	 */
	public void start() {
		_started = true;
	}
	
	/*
	 * Draw the fireworks.
	 */
	public void draw(Graphics g, int offsetX, int offsetY) {
		synchronized(_fireworks) {
			for(Firework firework : _fireworks) {
				firework.draw(g, offsetX, offsetY);
			}
		}
	}
	
	private Firework generateRandomFirework() {
		int x = (int) (Math.random() * _screenWidth);
		int particles = (int) (Math.random() * 20) + 10;
		int speed = (int) (Math.random() * 200) + 75;
		int particleSpeed = (int) (Math.random() * 100) + 50;
		int vertDistance = (int) (Math.random() * (_screenHeight - 100)) + 100;
		int blastRadius = (int) (Math.random() * 100 ) + 50;
		int trailLength = (int) (Math.random() * 50) + 15;
		Firework retval = new Firework(x, _screenHeight, particles, speed, particleSpeed, vertDistance, blastRadius, trailLength, getRandomColor());
		return retval;
	}
	
	private Color getRandomColor() {
		int color = (int) Math.floor((Math.random() * 8));
		switch(color) {
			case 0:
				return Color.BLUE;
			case 1:
				return Color.CYAN;
			case 2:
				return Color.GREEN;
			case 3: 
				return Color.MAGENTA;
			case 4:
				return Color.ORANGE;
			case 5:
				return Color.PINK;
			case 6:
				return Color.WHITE;
			case 7: 
				return Color.YELLOW;
		}
		return null;
	}
}
